home *** CD-ROM | disk | FTP | other *** search
/ HAKERIS 11 / HAKERIS 11.ISO / linux / system / LinuxConsole 0.4 / linuxconsole0.4install-en.iso / opt0.4.lcm / bin / hsfdcpd < prev    next >
Encoding:
Text File  |  2004-02-26  |  5.3 KB  |  227 lines

  1. #!/usr/bin/perl
  2. #
  3. # Copyright (c) 2003 Linuxant inc.
  4. #
  5. # NOTE: The use and distribution of this software is governed by the terms in
  6. # the file LICENSE, which is included in the package. You must read this and
  7. # agree to these terms before using or distributing this software.
  8. #
  9. # This script is called as a usermodehelper to start and stop the
  10. # DCP (Digital Call Progress) audio monitoring playback process for
  11. # the Conexant HSF softmodem driver under Linux.
  12. #
  13. # It tries to be as system and distribution-neutral as possible.
  14.  
  15. $CNXTDCPDEVICE=$ENV{'CNXTDCPDEVICE'};
  16. if ($CNXTDCPDEVICE eq "") {
  17.     $CNXTDCPDEVICE=0;
  18. }
  19.  
  20. $piddir="/var/run";
  21. $pidfile="$piddir/hsfdcpd$CNXTDCPDEVICE.pid";
  22.  
  23. $CNXTDCPACTION=$ENV{'CNXTDCPACTION'};
  24. if ($CNXTDCPACTION) {
  25.     open STDOUT, ">/var/run/hsfdcpd$CNXTDCPDEVICE.out";
  26.     open STDERR, ">/var/run/hsfdcpd$CNXTDCPDEVICE.err";
  27.     open STDIN, "</dev/null";
  28. }
  29.  
  30. if ($CNXTDCPACTION eq "start") {
  31.     if($pid=fork) {
  32.         # parent
  33.         exit 0;
  34.     } elsif (defined $pid) {
  35.         # child continues
  36.         $inchild=1;
  37.         open PIDFILE, ">$pidfile" or die "$0: can't create $pidfile: $!\n";
  38.         print PIDFILE "$$\n";
  39.         close PIDFILE;
  40.     } else {
  41.         die "$0: fork failed: $!\n";
  42.     }
  43.  
  44. } elsif ($CNXTDCPACTION eq "stop") {
  45.     open PIDFILE, "<$pidfile" or die "$0: can't open $pidfile: $!\n";
  46.     $pid=<PIDFILE>;
  47.     chop $pid;
  48.     close PIDFILE;
  49.     if ($pid > 0) {
  50.         kill 'TERM', $pid; # or die "$0: kill $pid failed: $!\n";
  51.     }
  52.     exit 0;
  53. } elsif ($CNXTDCPACTION eq "") {
  54. } else {
  55.     die "$0: invalid CNXTDCPACTION\n";
  56. }
  57.  
  58. END {
  59.     if ($inchild) {
  60.         unlink $pidfile;
  61.     }
  62. }
  63.  
  64. $SIG{TERM} = sub { exit; }; # execute END block
  65. $SIG{INT} = sub { exit; }; # execute END block
  66. $SIG{PIPE} = sub { };
  67.  
  68. use Errno;
  69. use Fcntl;
  70.  
  71. $dcpdev="/dev/hsfdcp$CNXTDCPDEVICE";
  72.  
  73. sysopen DCPDEV, "$dcpdev", (O_RDONLY | O_NDELAY | O_NONBLOCK) or die "$0: can't open $dcpdev";
  74.  
  75. $CNXTDCPRATE=$ENV{'CNXTDCPRATE'};
  76. if ($CNXTDCPRATE eq "") {
  77.     $CNXTDCPRATE=16000;
  78. }
  79.  
  80. $blocksize=2048;
  81.  
  82. $AFMT_S16_LE=0x10;
  83. $AFMT_S16_BE=0x20;
  84. $SNDCTL_DSP_RESET=0x5000;
  85. $SNDCTL_DSP_STEREO=0xc0045003;
  86. $SNDCTL_DSP_CHANNELS=0xc0045006;
  87. $SNDCTL_DSP_SETFMT=0xc0045005;
  88. $SNDCTL_DSP_SPEED=0xc0045002;
  89. $SNDCTL_DSP_SETFRAGMENT=0xc004500a;
  90.  
  91. $snddev = "/dev/dsp";
  92.  
  93. $sndfrag = (0x7fff << 16) | (log($blocksize)/log(2));
  94.  
  95. $sndstereo = 0;
  96.  
  97. $sndchan = 1;
  98.  
  99. $sndfmt = $AFMT_S16_LE;
  100.  
  101. $sndspeed = $CNXTDCPRATE;
  102.  
  103. $rin = $win = $ein = "";
  104. vec($rin, fileno(DCPDEV), 1) = 1;
  105. $ein = $rin | $win;
  106.  
  107. # start with two-block buffer to prevent underruns
  108. $buffersize=2*$blocksize;
  109.  
  110. $buf = pack("a$buffersize", "");
  111.  
  112. $timeout=undef;
  113.  
  114. $len=0;
  115. $buflen=$buffersize;
  116.  
  117. while(1) {
  118.  
  119.     ($nfound, $timeleft) = select($rout=$rin, $wout=$win, $eout=$ein, $timeout);
  120.  
  121.     if ($nfound > 0) {
  122.         if($rout eq $rin) {
  123.             $r = sysread DCPDEV, $buf, $buflen - $len, $len;
  124.             if ($r <= 0) {
  125.                 die "$0: read from $dcpdev: $!\n";
  126.             } else {
  127.                 $len += $r;
  128.             }
  129.             if ($len == $buflen) {
  130.                 if((!defined(fileno(DSPDEV))) && (!defined(fileno(RECORD)))) {
  131.  
  132.                     if (! -e "/etc/hsfmodem/nodcpaudio") {
  133.                         $sndfragarg = pack("L", $sndfrag);
  134.                         $sndstereoarg = pack("L", $sndstereo);
  135.                         $sndchanarg = pack("L", $sndchan);
  136.                         $sndfmtarg = pack("L", $sndfmt);
  137.                         $sndspeedarg = pack("L", $sndspeed);
  138.  
  139.                         if (!((sysopen DSPDEV, "$snddev", (O_WRONLY | O_NDELAY | O_NONBLOCK)) &&
  140.                             ioctl(DSPDEV, $SNDCTL_DSP_RESET, 0) &&
  141.                             ioctl(DSPDEV, $SNDCTL_DSP_SETFRAGMENT, $sndfragarg) &&
  142.                             ioctl(DSPDEV, $SNDCTL_DSP_STEREO, $sndstereoarg) &&
  143.                             ioctl(DSPDEV, $SNDCTL_DSP_CHANNELS, $sndchanarg) &&
  144.                             ioctl(DSPDEV, $SNDCTL_DSP_SETFMT, $sndfmtarg) &&
  145.                             ioctl(DSPDEV, $SNDCTL_DSP_SPEED, $sndspeedarg)
  146.                         )) {
  147.                             print STDERR "$0: can't use $snddev: $!\n";
  148.                             open DSPDEV, "|sox -t raw -r $CNXTDCPRATE -sw -c 1 - -t ossdsp $snddev" or print STDERR "$0: can't open sox pipe either: $!\n";
  149.                             $convertsamplestostereo = undef;
  150.                         } else {
  151.                             $convertsamplestostereo = unpack("L", $sndstereoarg);
  152.                         }
  153.                     }
  154.  
  155.                     if((!defined(fileno(RECORD))) && (-d "/etc/hsfmodem/dcprecord")) {
  156.                         $cnt=0;
  157.                         while(1) {
  158.                             $recfn= sprintf "/etc/hsfmodem/dcprecord/%03d", $cnt;
  159.                             if(sysopen (RECORD, $recfn, O_WRONLY | O_CREAT | O_EXCL, 0600)) {
  160.                                 last;
  161.                             }
  162.                             if ($!{EEXIST}) {
  163.                                 $cnt++;
  164.                                 next;
  165.                             }
  166.                             print STDERR "$0: sysopen $recfn: $!\n";
  167.                             last;
  168.                         }
  169.                     }
  170.  
  171.                     $timeout=0.5;
  172.                 }
  173.  
  174.                 if(defined(fileno(RECORD))) {
  175.                     $w = syswrite RECORD, $buf, $len;
  176.                     if ($w != $len) {
  177.                         print STDERR "$0: syswrite record $len returned $w ($!)\n";
  178.                     }
  179.                 }
  180.  
  181.                 if(defined(fileno(DSPDEV))) {
  182.                     if ($convertsamplestostereo) {
  183.                         @samples=unpack("S*", $buf);
  184.                         for ($c = 0; $c < @samples; $c++) {
  185.                             $samples[$c] = $samples[$c] | ($samples[$c] << 16);
  186.                         }
  187.                         $buf = pack("L*", @samples);
  188.                         $len *= 2;
  189.                     }
  190.                     $w = syswrite DSPDEV, $buf, $len;
  191.                     if ($w != $len) {
  192.                         print STDERR "$0: syswrite $len returned $w ($!)\n";
  193.                         if ($!{EPIPE}) {
  194.                             close DSPDEV;
  195.                         }
  196.                     }
  197.                 }
  198.  
  199.                 if((!defined(fileno(DSPDEV))) && (!defined(fileno(RECORD)))) {
  200.                     sleep 5; # delay retry
  201.                     $len=0;
  202.                     $buflen=$buffersize;
  203.                     while(sysread(DCPDEV, $buf, $buflen) > 0) {};
  204.                     next;
  205.                 }
  206.  
  207.                 $len = 0;
  208.                 $buflen = $blocksize;
  209.             }
  210.         }
  211.         if($eout eq $ein) {
  212.             print STDERR "$0: eout\n";
  213.         }
  214.     } else {
  215.         # timeout
  216.         if(defined(fileno(DSPDEV))) {
  217.             close DSPDEV;
  218.         }
  219.         if(defined(fileno(RECORD))) {
  220.             close RECORD;
  221.         }
  222.         $timeout=undef;
  223.         $len=0;
  224.         $buflen=$buffersize;
  225.     }
  226. }
  227.